/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.ebt.m.customer.util;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;

import com.ebt.m.AppContext;
import com.ebt.m.R;

import junit.framework.Assert;

/**
 * A drawable that encapsulates all the functionality needed to display a letter tile to
 * represent a contact image.
 */
public class LetterTileDrawable extends Drawable {

    private final String TAG = "LetterTileDrawable";

//    private final Paint mPaint;

    /** Letter tile */
    private static TypedArray sColors;
    private static int sDefaultColor;
    private static int sTileFontColor;
    private static float sLetterToTileRatio;
    private static Bitmap DEFAULT_PERSON_AVATAR;
    private static Bitmap DEFAULT_BUSINESS_AVATAR;
    private static Bitmap DEFAULT_VOICEMAIL_AVATAR;

    /** Reusable components to avoid new allocations */
    private static final Paint sPaint = new Paint();
    private static final Rect sRect = new Rect();

    /** Contact type constants */
    public static final int TYPE_PERSON = 1;
    public static final int TYPE_BUSINESS = 2;
    public static final int TYPE_VOICEMAIL = 3;
    public static final int TYPE_DEFAULT = TYPE_PERSON;

    private volatile String mDisplayName;
    private String mIdentifier;
    private int mContactType = TYPE_DEFAULT;
    private float mScale = 1.0f;
    private float mOffset = 0.0f;

    /** This should match the total number of colors defined in colors.xml for letter_tile_color */
    private static final int NUM_OF_TILE_COLORS = 8;

//    public static final int TYPE_DEFAULT = LetterTileDrawable.TYPE_DEFAULT;

    /** Scale and offset default constants used for default letter images */

//    public static final float SCALE_DEFAULT = 1.0f;
    public static final float SCALE_DEFAULT = 0.75f;
    public static final float OFFSET_DEFAULT = -0.12f;
    
    public LetterTileDrawable(final Resources res) {
//        mPaint = new Paint();
//        mPaint.setFilterBitmap(true);
//        mPaint.setDither(true);

        if (sColors == null) {
            sColors = res.obtainTypedArray(R.array.letter_tile_colors);
            sDefaultColor = res.getColor(R.color.letter_tile_default_color);
            sTileFontColor = res.getColor(R.color.letter_tile_font_color);
            sLetterToTileRatio = res.getFraction(R.dimen.letter_to_tile_ratio, 1, 1);
            DEFAULT_PERSON_AVATAR = BitmapFactory.decodeResource(res,
                    R.drawable.button_blue_circle);
            DEFAULT_BUSINESS_AVATAR = BitmapFactory.decodeResource(res,
                    R.drawable.button_blue_circle);
            DEFAULT_VOICEMAIL_AVATAR = BitmapFactory.decodeResource(res,
                    R.drawable.button_blue_circle);
            sPaint.setTypeface(Typeface.create(
                    res.getString(R.string.letter_tile_letter_font_family), Typeface.NORMAL));
            sPaint.setTextAlign(Align.CENTER);
            sPaint.setAntiAlias(true);
        }
    }

    @Override
    public void draw(final Canvas canvas) {
        final Rect bounds = getBounds();
        if (!isVisible() || bounds.isEmpty()) {
            return;
        }
        // Draw letter tile.
        drawLetterTile(canvas);
    }


    private synchronized void drawLetterTile(final Canvas canvas) {
        // Draw background color.
        sPaint.setColor(pickColor(mIdentifier));

        //canvas.drawRect(getBounds(), sPaint);
        canvas.drawCircle((getBounds().centerX()), (getBounds().centerY()), (getBounds().centerY()), sPaint);

        // Draw letter/digit only if the first character is an english letter
        if (mDisplayName != null /*&& isEnglishLetter(mDisplayName.charAt(0))*/) {
            // Draw letter or digit.
            mDisplayName = mDisplayName.trim();
            char[] sLastChar = new char[1];
            sLastChar[0] = Character.toUpperCase(mDisplayName.charAt(0));

            // Scale text by canvas bounds and user selected scaling factor
            final int minDimension = Math.min(getBounds().width(), getBounds().height());
            sPaint.setTextSize(mScale * sLetterToTileRatio * minDimension);
            //sPaint.setTextSize(sTileLetterFontSize);
            sPaint.getTextBounds(sLastChar, 0, 1, sRect);
            sPaint.setColor(sTileFontColor);
            final Rect bounds = getBounds();


            // Draw the letter in the canvas, vertically shifted up or down by the user-defined
            // offset
            canvas.drawText(sLastChar, 0, 1, minDimension / 2,
                    bounds.centerY() + mOffset * bounds.height() + (bounds.height() - sRect.height()) / 2,
                    sPaint);

        }
    }

    /**
     * Returns a deterministic color based on the provided contact identifier string.
     */
    private int pickColor(final String identifier) {
//        if (TextUtils.isEmpty(identifier) || mContactType == TYPE_VOICEMAIL) {
//            return sDefaultColor;
//        }
        // String.hashCode() implementation is not supposed to change across java versions, so
        // this should guarantee the same email address always maps to the same color.
        // The email should already have been normalized by the ContactRequest.
        final int color = Math.abs(identifier.hashCode()) % NUM_OF_TILE_COLORS;
        return sColors.getColor(color, sDefaultColor);
    }

    private static Bitmap getBitmapForContactType(int contactType) {
        switch (contactType) {
            case TYPE_PERSON:
                return DEFAULT_PERSON_AVATAR;
            case TYPE_BUSINESS:
                return DEFAULT_BUSINESS_AVATAR;
            case TYPE_VOICEMAIL:
                return DEFAULT_VOICEMAIL_AVATAR;
            default:
                return DEFAULT_PERSON_AVATAR;
        }
    }

    @Override
    public void setAlpha(final int alpha) {
    }

    @Override
    public void setColorFilter(final ColorFilter cf) {
    }

    @Override
    public int getOpacity() {
        return android.graphics.PixelFormat.OPAQUE;
    }

    /**
     * Scale the drawn letter tile to a ratio of its default size
     *
     * @param scale The ratio the letter tile should be scaled to as a percentage of its default
     * size, from a scale of 0 to 2.0f. The default is 1.0f.
     */
    public void setScale(float scale) {
        mScale = scale;
    }

    /**
     * Assigns the vertical offset of the position of the letter tile to the ContactDrawable
     *
     * @param offset The provided offset must be within the range of -0.5f to 0.5f.
     * If set to -0.5f, the letter will be shifted upwards by 0.5 times the height of the canvas
     * it is being drawn on, which means it will be drawn with the center of the letter starting
     * at the top edge of the canvas.
     * If set to 0.5f, the letter will be shifted downwards by 0.5 times the height of the canvas
     * it is being drawn on, which means it will be drawn with the center of the letter starting
     * at the bottom edge of the canvas.
     * The default is 0.0f.
     */
    public void setOffset(float offset) {
        Assert.assertTrue(offset >= -0.5f && offset <= 0.5f);
        mOffset = offset;
    }

    public void setContactDetails(final String displayName, final String identifier) {
        mDisplayName = displayName;
        mIdentifier = identifier;
    }

    public void setContactType(int contactType) {
        mContactType = contactType;
    }

    public static Drawable getDefaultImageForContact(Context context,
              DefaultImageRequest defaultImageRequest) {
        if(!(context instanceof AppContext)){
            context = context.getApplicationContext();
        }
        final LetterTileDrawable drawable = new LetterTileDrawable(context.getResources());
        if (defaultImageRequest != null) {
            // If the contact identifier is null or empty, fallback to the
            // displayName. In that case, use {@code null} for the contact's
            // display name so that a default bitmap will be used instead of a
            // letter
            if (TextUtils.isEmpty(defaultImageRequest.identifier)) {
//                drawable.setContactDetails(null, defaultImageRequest.displayName);
            	drawable.setContactDetails(defaultImageRequest.displayName, null);
            } else {
                drawable.setContactDetails(defaultImageRequest.displayName,
                        defaultImageRequest.identifier);
            }
            drawable.setContactType(defaultImageRequest.contactType);
            drawable.setScale(defaultImageRequest.scale);
            drawable.setOffset(defaultImageRequest.offset);
        }
        return drawable;
    }
    
    public static class DefaultImageRequest {
        /**
         * The contact's display name. The display name is used to
         */
        public String displayName;
        /**
         * A unique and deterministic string that can be used to identify this contact. This is
         * usually the contact's lookup key, but other contact details can be used as well,
         * especially for non-local or temporary contacts that might not have a lookup key. This
         * is used to determine the color of the tile.
         */
        public String identifier;
        /**
         * The type of this contact. This contact type may be used to decide the kind of
         * image to use in the case where a unique letter cannot be generated from the contact's
         * display name and identifier. See:
         * {@link #TYPE_PERSON}
         * {@link #TYPE_BUSINESS}
         * {@link #TYPE_PERSON}
         * {@link #TYPE_DEFAULT}
         */
        public int contactType = TYPE_DEFAULT;
        /**
         * The amount to scale the letter or bitmap to, as a ratio of its default size (from a
         * range of 0.0f to 2.0f). The default value is 1.0f.
         */
        public float scale = SCALE_DEFAULT;
        /**
         * The amount to vertically offset the letter or image to within the tile.
         * The provided offset must be within the range of -0.5f to 0.5f.
         * If set to -0.5f, the letter will be shifted upwards by 0.5 times the height of the canvas
         * it is being drawn on, which means it will be drawn with the center of the letter starting
         * at the top edge of the canvas.
         * If set to 0.5f, the letter will be shifted downwards by 0.5 times the height of the
         * canvas it is being drawn on, which means it will be drawn with the center of the letter
         * starting at the bottom edge of the canvas.
         * The default is 0.0f, which means the letter is drawn in the exact vertical center of
         * the tile.
         */
        public float offset = OFFSET_DEFAULT;

        public DefaultImageRequest() {
        }

        public DefaultImageRequest(String displayName, String identifier) {
            this(displayName, identifier, TYPE_DEFAULT, SCALE_DEFAULT, OFFSET_DEFAULT);
        }

        public DefaultImageRequest(String displayName, String identifier, int contactType) {
            this(displayName, identifier, contactType, SCALE_DEFAULT, OFFSET_DEFAULT);
        }

        public DefaultImageRequest(String displayName, String identifier, int contactType,
                float scale, float offset) {
            this.displayName = displayName;
            this.identifier = identifier;
            this.contactType = contactType;
            this.scale = scale;
            this.offset = offset;
        }
    }
    
}
